package org.flowers.unbeaten.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.flowers.unbeaten.base.constant.Constants;
import org.flowers.unbeaten.base.entity.*;
import org.flowers.unbeaten.config.proprety.CustomerRedisProperty;
import org.flowers.unbeaten.exception.BusinessException;
import org.flowers.unbeaten.exception.code.BaseResponseCode;
import org.flowers.unbeaten.mapper.UserMapper;
import org.flowers.unbeaten.service.*;
import org.flowers.unbeaten.util.*;
import org.flowers.unbeaten.base.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author RyanWang
 * @since 2021-07-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IDepartmentService departmentService;

    @Autowired
    private IUserRoleService userRoleService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private HttpSessionUtils httpSessionUtils;

    @Autowired
    private CustomerRedisProperty customerRedisProperty;

    @Override
    public PageVo<User> getUserPageList(User user, BaseEntity baseEntity) {
        PageHelper.startPage(baseEntity.getPage(), baseEntity.getLimit());
        List<User> users = userMapper.selectUsers(user);
        return PageUtils.getPageVo(users);
    }

    @Override
    public UserVo login(LoginVo vo) {
        User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, vo.getUsername()));
        if (Objects.isNull(user)) {
            throw new BusinessException(BaseResponseCode.ACCOUNT_NOT_FIND);
        }
        if (user.getStatus() == 0) {
            throw new BusinessException(BaseResponseCode.USER_LOCK);
        }
        if (!PasswordUtils.validatePassword(vo.getPassword(), user.getPassword(), user.getSalt())) {
            throw new BusinessException(BaseResponseCode.PASSWORD_ERROR);
        }
        UserVo userVo = new UserVo();
        userVo.setUserId(user.getUserId());
        userVo.setAvatarUrl(user.getAvatar());
        userVo.setUsername(user.getUsername());
        userVo.setDepartmentId(user.getDepartmentId());
        userVo.setPhone(user.getPhone());

        // 是否删除之前token此处控制是否支持多登陆端
        // true:允许多处登陆;
        // false:只能单处登陆，顶掉之前登陆
        if (!customerRedisProperty.getAllowMultipleLogin()) {
            httpSessionUtils.abortUserByUserId(user.getUserId());
        }
        if (StringUtils.isNotBlank(user.getDepartmentId())) {
            Department department = departmentService.getById(user.getDepartmentId());
            if (department != null) {
//                sysUser.setDeptNo(sysDept.getDeptNo());
            }
        }
        String token = httpSessionUtils.createTokenAndUser(user, roleService.getRoleNames(user.getUserId()), menuService.getPermissionsByUserId(user.getUserId()));
        userVo.setAccessToken(token);

        return userVo;
    }

    @Override
    public DashboardVo getDashboard(String userId) {

        User user = userMapper.selectById(userId);
        UserVo userVo = new UserVo();

        if (Objects.nonNull(user)) {
            userVo.setUserId(user.getUserId());
            userVo.setUsername(user.getUsername());
            userVo.setPhone(user.getPhone());
            userVo.setAvatarUrl(user.getAvatar());
            Department department = departmentService.getById(user.getDepartmentId());
            if (Objects.nonNull(department)) {
                userVo.setDepartmentId(department.getDepartmentId());
                userVo.setDepartmentName(department.getDepartmentName());
            }
        }

        List<MenuVo> menuTreeList = menuService.getMenuTreeList(userId);
        DashboardVo dashboardVo = new DashboardVo();
        dashboardVo.setUserVo(userVo);
        dashboardVo.setMenuVos(menuTreeList);

        return dashboardVo;
    }

    @Override
    public void add(User user) {
        User one = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));
        if (Objects.nonNull(one)) {
            throw new BusinessException("用户已存在，请勿重复添加！");
        }
        user.setUserId(Id.generateId());
        user.setSalt(Token.createSalt(Constants.SALT_SIZE));
        user.setPassword(PasswordUtils.encodePassword(user.getPassword(), user.getSalt()));
        userMapper.insert(user);
        if (!CollectionUtils.isEmpty(user.getRoleIds())) {
            UserRoleVo vo = new UserRoleVo();
            vo.setUserId(user.getUserId());
            vo.setRoleIds(user.getRoleIds());
            userRoleService.add(vo);
        }
    }

    @Override
    public void edit(User user) {
        User usr = userMapper.selectById(user.getUserId());
        if (Objects.isNull(usr)) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }

        // 如果用户名变更
        if (!usr.getUsername().equals(user.getUsername())) {
            User one = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));
            if (Objects.nonNull(one)) {
                throw new BusinessException("用户名已存在！");
            }
        }

        //如果用户名、密码、状态 变更，删除redis中用户绑定的角色跟权限
        if (!usr.getUsername().equals(user.getUsername())
                || (!StringUtils.isEmpty(user.getPassword())
                && !usr.getPassword().equals(PasswordUtils.encodePassword(user.getPassword(), usr.getSalt())))
                || !usr.getStatus().equals(user.getStatus())) {
            httpSessionUtils.abortUserByUserId(user.getUserId());
        }

        if (!StringUtils.isEmpty(user.getPassword())) {
            String newPassword = PasswordUtils.encodePassword(user.getPassword(), usr.getSalt());
            user.setPassword(newPassword);
        } else {
            user.setPassword(null);
        }
        userMapper.updateById(user);
    }

    @Override
    public void delete(List<String> ids) {
        // 删除用户，删除redis的绑定的角色跟权限
        httpSessionUtils.abortUserByUserIds(ids);
        userMapper.delete(new LambdaQueryWrapper<User>().in(User::getUserId, ids));
    }

    @Override
    public void changePassword(PasswordVo vo) {
        User user = userMapper.selectById(vo.getUserId());
        if (Objects.isNull(user)) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }

        if (!PasswordUtils.validatePassword(vo.getOldPassword(), user.getPassword(), user.getSalt())) {
            throw new BusinessException(BaseResponseCode.OLD_PASSWORD_ERROR);
        }
        user.setPassword(PasswordUtils.encodePassword(vo.getNewPassword(), user.getSalt()));
        userMapper.updateById(user);
        // 退出用户
        httpSessionUtils.abortAllUserByToken();
    }

    @Override
    public UserOwnRoleVo getUserOwnRole(String userId) {
        List<String> roleIds = userRoleService.getRoleIdsByUserId(userId);
        List<Role> list = roleService.list();
        UserOwnRoleVo vo = new UserOwnRoleVo();
        vo.setRoles(list);
        vo.setRoleIds(roleIds);
        return vo;
    }

    @Override
    public void setUserOwnRole(UserRoleVo vo) {
        // 删除之前绑定的角色
        userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, vo.getUserId()));
        if (!CollectionUtils.isEmpty(vo.getRoleIds())) {
            userRoleService.add(vo);
        }
        // 刷新权限
        httpSessionUtils.refreshUerId(vo.getUserId());
    }
}
